package cn.enjoy.tool.utils.select;

import lombok.Data;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 选择器
 *
 * @param <P> param变量
 * @param <T> 返回类型
 * @author K
 */
@Data
public class Selector<P, T> {

    private boolean selected = false;
    private P param;
    private Function<P, T> factory;

    Selector(P param) {
        this.param = param;
    }


    public static <P, T> Selector<P, T> param(P param) {
        return new Selector<>(param);
    }

    /**
     * 判断是否命中分支
     * 第一次进来 !selected为true，判断test(param)
     * 如果通过，就给factory赋值，同时selected设为true，后面就不会判断；不通过最后返回this继续操作
     *
     * @param branch 分支
     * @return Selector<P, T>
     */
    public Selector<P, T> test(Branch<P, T> branch) {
        if (!selected) {
            boolean pass = branch.tester().test(param);
            if (pass) {
                selected = true;
                factory = branch.factory();
            }
        }
        return this;
    }

    /**
     * 结束，命中返回factory函数计算得到的值，否则使用or提供的值
     *
     * @param supplier 结果供应者
     * @return T 默认值
     */
    public T or(Supplier<T> supplier) {
        return selected ? this.factory.apply(param) : supplier.get();
    }

    /**
     * 结束，命中返回factory函数计算得到的值，否则使用or提供的值
     *
     * @param t 最后的默认值
     * @return T 默认值
     */
    public T or(T t) {
        return or(() -> t);
    }

    /**
     * 当前选择器是否已经选择分支
     *
     * @return 如果已经存在分支被击中，则返回 true；否则返回 false
     */
    public boolean isSelected() {
        return selected;
    }

    @Override
    public String toString() {
        return String.format("Selector{success=%s}", selected);
    }

}
